# -*- coding: utf-8 -*-
'''
#----------------------------------------------------------------------------------------
#功能：策划服快速发布更新
#      操作过程中遇到错误立即退出
#----------------------------------------------------------------------------------------
'''

import os
import stat
import argparse
from flib.utils import *
from flib.SVN import SVN,SvnRecord

@quit
def safe_exec(cmds, logout=True):
    return execute(cmds=cmds, logout=logout)
@quit
def safe_sh(cmds, logout=False):
    return exec_sh(cmds=cmds, logout=logout)

# Unity操作
def UnityOp(project_path, execute_method, nc, argstring=""):
    consoleoutput = nc and "127.0.0.1:{0}".format(nc.get_port()) or ""
    unity_path = getenv("UNITY","F:/Program Files (x86)/Unity4.7.2/Editor/Unity.exe")
    logfile = project_path + "/unity.log"
    return safe_exec(cmds='''"{0}"
        -projectPath "{1}"
        -executeMethod {2}
        -logFile "{3}"
        -quit -batchmode
        --auto-switch-target true
        --consoleoutput {4}
        {5}'''.format(unity_path,
                     project_path,
                     execute_method,
                     logfile,
                     consoleoutput,
                     argstring))
# 导出美术资源
def export_arts(nc):
    ZLPrint("[session]", "开始导出美术资源")
    arts_project = getenv("ART_PATH","E:/Work-Space/SevenProgram/seven_art")
    # 更新svn
    result = safe_exec("svn update {0}".format(arts_project))
    for r in result:
        if r.find('   C ') != -1:
            f = r[5:]
            if os.path.exists(f):
                ZLPrint("[warning]", '''svn 更新遇到冲突：{0}'''.format(f))
                safe_exec('''svn revert "{0}"'''.format(f))
    # 开始导出
    ZLPrint("[info]", "开始执行Unity命令导出资源")
    UnityOp(arts_project, "BatchExportRes.BatchExportArtRes", nc, "--platform " + getenv("platform", "win"))
    ZLPrint("[session]", "结束导出美术资源")
# 导出界面资源
def export_ui(nc):
    ZLPrint("[session]", "开始导出界面资源")
    program_project = getenv("PROJECT_PATH","F:/Seven/ElementUnityWin")
    unity_project = program_project + "/UnityProject"
    # 更新svn
    result = safe_exec("svn update {}".format(program_project))
    for r in result:
        if r.find('   C ') != -1:
            f = r[5:]
            if os.path.exists(f):
                ZLPrint("[warning]", '''svn 更新遇到冲突：{0}'''.format(f))
                safe_exec('''svn revert "{0}"'''.format(f))
    # 开始导出
    ZLPrint("[info]", "开始执行Unity命令导出资源")
    UnityOp(unity_project, "BatchExportRes.BatchExportUIPrefab", nc, "--platform " + getenv("platform","win"))
    ZLPrint("[session]", "结束导出界面资源")
# 导资源
def export_unity_assets(args):
    nc = nc_server()
    nc.start()
#####################################################################################################
#暂时不考虑导出资源，仅更新程序代码
#####################################################################################################
def create_dir(_path):
    (dirpath, filename) = os.path.split(_path)
    if not os.path.exists(dirpath):
        os.makedirs(dirpath)

_SELF_PATH_ = os.path.split(os.path.realpath(__file__))[0].replace("\\", "/")
_DUMPCODE_FILE_ = os.getcwd().replace("\\", "/") + "/" + str(newuuid()) + ".lua"

def compile_one(luabin, sourcePath, destPath, chunkName):
    create_dir(destPath)
    ZLPrint("     编译脚本: " + chunkName)
    #去掉只读属性
    os.chmod(sourcePath, stat.S_IWRITE)
    safe_exec(cmds='''{luabin} "{script}" {args}'''.format(luabin=luabin, script=_DUMPCODE_FILE_, args=sourcePath+ " " + destPath + " " + chunkName), logout=False)

def update_client(args):
    records = args.versions.split(',')  # jenkins传入进来的是按照逗号分隔
    versions = []
    for v in records:
        r = SvnRecord.createSvnRecordFromString(v)
        if r: versions.append(r.version)
    if not versions:
        ZLPrint("没有可以更新的记录")
        return True
    #版本从小到大排列
    versions = sorted(versions, lambda a, b: cmp(a, b))
    local_dir = os.getcwd() + "/local_diff"
    svn_url = args.svn_host
    file_list = set()
    try:
        for v in versions:
            ZLPrint("检出版本",v)
            ret = SVN.export_record(svn_url,local_dir,v)
            for x in ret:
                file_list.add(x)
                if not x.endswith(".lua"):
                    if os.path.isfile(x): os.remove(x)
                else:
                    tempx = x.replace('\\', '/') + ".tmp.lua"
                    safe_sh(cmds='''mv -f "{source}" "{temp}"'''.format(source=x,temp=tempx))
                    tmpdir = local_dir.replace('\\', '/') + "/Output"
                    sourceFile = x.replace('\\', '/')
                    chunkName = sourceFile.lstrip(tmpdir)
                    ZLPrint("    ", chunkName)
                    compile_one("lua", tempx, x.replace('\\', '/'), chunkName)
                    safe_sh(cmds='''rm -rf "{temp}"'''.format(temp=tempx))
        # 开始上传更新
        ZLPrint("上传更新")
        safe_exec(cmds='''sh {tools_path}/make-client/resource-update.sh "../elementpacktool/ElementPackTool-pc.exe" {update_url} "{local_dir}"'''.format(
            tools_path=args.program_tools,
            update_url="http://10.236.100.38/seven_xevs/pc",
            local_dir=local_dir.replace('\\','/') + "/Output"), logout=True)
        return True
    except Exception as e:
        raise e
    finally:
        safe_sh(cmds='''rm -rf "{local_dir}"'''.format(local_dir=local_dir))

def update_data(args):
    records = args.versions.split(',')  # jenkins传入进来的是按照逗号分隔
    versions = []
    for v in records:
        r = SvnRecord.createSvnRecordFromString(v)
        if r: versions.append(r.version)
    if not versions:
        ZLPrint("没有可以更新的记录")
        return True
    # 版本从小到大排列
    versions = sorted(versions, lambda a, b: cmp(a, b))
    local_dir = os.getcwd() + "/local_diff"
    svn_url = args.svn_host
    file_list = set()
    try:
        for v in versions:
            ZLPrint("检出版本",v)
            ret = SVN.export_record(svn_url,local_dir,v)
            for x in ret:
                file_list.add(x)
                if not x.endswith(".lua") and not x.endswith(".txt") and not x.endswith(".txt") and not x.endswith(".prmap") and x.find(".data") == -1:
                    if os.path.isfile(x): os.remove(x)
                else:
                    tmpdir = local_dir.replace('\\', '/')
                    sourceFile = x.replace('\\', '/')
                    chunkName = sourceFile.replace(tmpdir+"/", "")
                    ZLPrint("    ", chunkName)
        # 开始上传更新
        ZLPrint("上传更新")
        safe_exec(cmds='''sh {tools_path}/make-client/resource-update.sh "../elementpacktool/ElementPackTool-pc.exe" {update_url} "{local_dir}"'''.format(
            tools_path=args.program_tools,
            update_url="http://10.236.100.38/seven_xevs/pc",
            local_dir=local_dir.replace('\\','/')), logout=True)
        return True
    except Exception as e:
        raise e
    finally:
        safe_sh(cmds='''rm -rf "{local_dir}"'''.format(local_dir=local_dir))

def init_lua_coder():
    strcmds = '''
    --lua scripts compile
    local sourcePath, destPath, chunkName = ...
    local fin = io.open(sourcePath)
    if not fin then
        io.stderr:write("failed to open file for reading: " .. chunkName)
        io.flush()
        os.exit(1)
    end
    local content = fin:read("*a")
    fin:close()

    local f, err = loadstring(content, "@" .. chunkName)
    if not f then
        io.stderr:write("failed to compile: " .. chunkName .. ": " .. err)
        os.exit(1)
    end
    local codeDump = string.dump(f)
    local fout = io.open(destPath, "wb")
    if not fout then
        io.stderr:write("failed to open file to write: " .. destPath)
        os.exit(1)
    end
    fout:write(codeDump)
    fout:close()
    os.exit(0)
    '''

    fscript = open(_DUMPCODE_FILE_, "w")
    fscript.write(strcmds)
    fscript.close()

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--user", help="svn用户", type=str, default="")
    parser.add_argument("--password", help="svn用户", type=str, default="")
    parser.add_argument("--svn-host", help="svn地址", type=str, default="http://10.236.192.18/svn/seven_client/trunk")
    parser.add_argument("--program-tools", help="程序工具文件", type=str, default="F:/Seven/ElementUnityWin/Tools")
    parser.add_argument("--versions", help="需要指定更新的记录", type=str, default="30596")
    parser.add_argument("--search-limit", help="最大搜索记录", type=int, default=500)
    parser.add_argument("--op", help="操作", type=str, default="")
    args = parser.parse_args()
    SVN.username = args.user
    SVN.password = args.password
    if args.op == "get_logs":
        svn_url = args.svn_host
        records = SVN.get_records(svn_url,args.search_limit)
        if not records:
            pass
        else:
            sout = ""
            for v in records:
                message = "{version}:{log}@{author}".format(version=v.version,author=v.author,log=v.log)
                sout += "\n" + "{message}".format(message=message).strip("\n").replace("\n", "").replace(",", " ")
            print sout
    elif args.op == "update_client":
        init_lua_coder()
        if not update_client(args):
            raise Exception("上传程序代码更新失败")
    elif args.op == "update_data":
        if not update_data(args):
            raise Exception("发布策划数据更新失败")
    else:
        raise "operation not implementation"

if __name__ == '__main__':
    try:
        main()
    except Exception as e:
        raise e
    finally:
        safe_sh(cmds='''rm -rf "{local_dir}"'''.format(local_dir=_DUMPCODE_FILE_))